
import Food from './Food' // 食物
import ScorePanel from './ScorePanel' // 计分板
import Snake from './Snake' // 蛇

// 存储方向相对应的反方向
enum directionMap {
    ArrowUp = "ArrowDown",
    ArrowDown = "ArrowUp",
    ArrowLeft = "ArrowRight",
    ArrowRight = "ArrowLeft",
}


class GameControl {
    snake: Snake; // 蛇
    food: Food; // 食物
    scorePanel: ScorePanel; // 计分板
    direction: string = 'ArrowRight'; // 蛇移动方向
    gameOver: Boolean = false; // 游戏是否结束
    
    constructor() {
        this.snake = new Snake()
        this.food = new Food()
        this.scorePanel = new ScorePanel()
        this.init()
    }

    // 游戏初始化
    init() {
        // 绑定键盘按下事件
        document.addEventListener('keydown', this.keyDownHandler.bind(this))
        // 随机生成食物
        this.food.change()
        // 蛇运动
        this.run()
    }

    /**
     * 键盘按下事件
     * @param event 
     * ArrowUp
     * ArrowDown
     * ArrowLeft
     * ArrowRight
     */
    keyDownHandler(event: KeyboardEvent) {
        // 如果有蛇身，不能调头；如果没有蛇身，可以调头
        if (this.snake.bodies.length > 1) {
            // 将要移动的方向
            const new_direction = event.key as keyof typeof directionMap 
            // 获取将要移动反向对应的反方向
            const re_new_direction = directionMap[new_direction]
            // 存储蛇移动方向
            this.direction = this.direction === re_new_direction ? this.direction : event.key 
        } else {
            this.direction = event.key // 存储蛇移动方向
        }
    }

    // 蛇移动方法
    run() {
        // 获取蛇当前坐标
        let x = this.snake.X
        let y = this.snake.Y

        switch(this.direction) {
            case "ArrowUp":
                y -= 10
                break;
            case "ArrowDown":
                y += 10
                break;
            case "ArrowLeft":
                x -= 10
                break;
            case "ArrowRight":
                x += 10
                break;
        }
        this.checkEat(x, y)
        

        // 修改蛇位置
        try {
            this.snake.X = x
            this.snake.Y = y
        } catch(e:any) {
            alert('游戏结束！')
            this.gameOver = true // 游戏终止
        }
        
        

        // 开始定时器
        !this.gameOver && setTimeout(() => {
            this.run()
        }, 300 - (this.scorePanel.level - 1) * 30)

    }

    // 检查蛇是否吃到食物
    checkEat(X:number, Y:number) {
        if (X === this.food.x && Y === this.food.y) {
            this.snake.addBody() // 蛇增加身体
            this.food.change() // 重置食物位置
            this.scorePanel.addScore() // 分数增加
        }
    }
}

export default GameControl